package com.googlecode.dgwt.client.dojo.data.base;

import java.util.AbstractList;
import java.util.Collection;

import com.googlecode.dgwt.client.dojo.data.listener.DataListener;

/**
 * @author wellsantos@wellsantos.com
 * @since 0.01
 */
public abstract class StoreEngine<Item> extends AbstractList<Item> {
    
    private Collection<Item> itemList;
    private StoreListenerList<Item, DataListener<Item>> listenerList; 
    
    
    public StoreEngine(Store<Item> store, int initialCapacity) {
        listenerList = createListenerList(store);
        itemList = createItemList(store, initialCapacity);
    }
    
    
    protected abstract Collection<Item> createItemList(Store<Item> store, int initialCapacity);

    
    protected StoreListenerList<Item, DataListener<Item>> createListenerList(Store<Item> store){
        return new StoreListenerList<Item, DataListener<Item>>(store);
    }
    
    protected void setItemList(Collection<Item> itemList){
        this.itemList = itemList;
    }
    
    public Collection<Item> getItemList(){
        return itemList;
    }
    
    public StoreListenerList<Item, DataListener<Item>> getDataListenerList(){
        return listenerList;
    }
    

    // Item Operations
    
    
    @Override
    public Item get(int index) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void add(int index, Item element) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Item remove(int index) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Item set(int index, Item element) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int indexOf(Object o) {
        return -1;
    }


    @Override
    public boolean add(Item item) {
        assert (item != null) : "Can't add a NULL item to a Store";
        int index = getItemList().size();
        if (getItemList().add(item)) {
            onAdd(index, item);
            return true;
        }
        return false;
    }

    @Override
    @SuppressWarnings("unchecked")
    public boolean remove(Object item) {
        if (getItemList().remove(item)) {
            onRemove(indexOf(item), (Item) item);
            return true;
        }
        return false;
    }
    
    @Override
    public int size() {
        return getItemList().size();
    }


    // Listener Events
    
    
    public void onAdd(int index, Item item) {
        for (DataListener<Item> listener : getDataListenerList()) {
            listener.onAdd(index, item);
        }
    }

    public void onFetch(int index, Item item) {
        for (DataListener<Item> listener : getDataListenerList()) {
            listener.onFetch(index, item);
        }
    }

    public void onRefresh() {
        for (DataListener<Item> listener : getDataListenerList()) {
            listener.onRefresh();
        }
    }

    public void onRefreshItem(Item item) {
        for (DataListener<Item> listener : getDataListenerList()) {
            listener.onRefreshItem(item);
        }
    }

    public void onModified(Item item) {
        for (DataListener<Item> listener : getDataListenerList()) {
            listener.onModified(item);
        }
    }

    public void onRemove(int index, Item item) {
        for (DataListener<Item> listener : getDataListenerList()) {
            listener.onRemove(index, item);
        }
    }

    public void onReplace(int index, Item oldItem, Item newItem) {
        for (DataListener<Item> listener : getDataListenerList()) {
            listener.onReplace(index, oldItem, newItem);
        }
    }

    public void onRefreshValue(Item item, int columnIndex) {
        for (DataListener<Item> listener : getDataListenerList()) {
            listener.onRefreshValue(item, columnIndex);
        }
    }

}